package org.dce.screencapturer.actions.objects;

import java.awt.BasicStroke;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Stroke;

import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JList;

import org.dce.screencapturer.actions.DropDownAction;
import org.dce.screencapturer.objects.DrawingObject;
import org.dce.screencapturer.objects.LineAttributes;
import org.dce.screencapturer.objects.ShapeObject;

@SuppressWarnings("serial")
public class SelectStrokeAction extends DropDownAction {
	
	public SelectStrokeAction() {
		super("categories.object", "actions.selectStroke", null);

		DefaultListModel model = new DefaultListModel();
		
		model.addElement(new Pattern(0));
		
		for (int i=1;i<=30;i++){
			model.addElement(new Pattern(1,i+1,i));
			model.addElement(new Pattern(1,i,i+1));
		}
		
		setModel(model);
		setRenderer(new StrokeRenderer());

	}
	@Override
	protected void itemSelected(Object object) {
		
		ShapeObject shapeObject = (ShapeObject)getObject();
		
		LineAttributes lineAttributes = (LineAttributes) shapeObject.getLineAttributes().clone();
		
		lineAttributes.setStroke(createStroke((Pattern)object,lineAttributes.getStroke().getLineWidth()));
		
		shapeObject.setLineAttributes(lineAttributes);
		
		System.out.println(object);
	}

	private BasicStroke createStroke(Pattern pattern,float lineWidth) {
		
		BasicStroke stroke = new BasicStroke(
				lineWidth, 
				BasicStroke.CAP_SQUARE, 
				BasicStroke.JOIN_ROUND, 
				0,
				pattern.dash,
				pattern.dashPhase);
		
		return stroke;
	}
	
	private class StrokeRenderer 
		extends DefaultListCellRenderer {

		private Pattern value;
		
		@Override
		public Component getListCellRendererComponent(JList list, Object value,
				int index, boolean isSelected, boolean cellHasFocus) {

			Component component = super.getListCellRendererComponent(list, value, index, isSelected,
					cellHasFocus);
			
			component.setPreferredSize(new Dimension(60,22));

			this.value = (Pattern)value;
			
			return component;
		}
		
		protected void paintComponent(Graphics g){
			
			Insets insets = getInsets();
			
			g.setColor(getBackground());
			
			g.fillRect(0,0,getWidth()-1,getHeight()-1);
			
			g.setColor(getForeground());
			
			BasicStroke stroke = new BasicStroke(
				1, 
				BasicStroke.CAP_SQUARE, 
				BasicStroke.JOIN_ROUND, 
				0,
				value.dash,
				value.dashPhase);
			
			Graphics2D g2d = (Graphics2D)g;
			
			Stroke current = g2d.getStroke();
			
			g2d.setStroke(stroke);
			
			g.drawLine(insets.left, getHeight()/2, getWidth()-insets.right-insets.left, getHeight()/2);
			
			g2d.setStroke(current);
		}
	}
	
	private class Pattern {
		private float dashPhase;
		private float[] dash;
		
		public Pattern(float dashPhase, float ... dash){
			this.dashPhase = dashPhase;
			this.dash = (dash == null || dash.length == 0) ? null : dash;
		}
		
		public int hashCode(){
			return (toString(dash)+dashPhase).hashCode();
		}
		
		public boolean equals(Object other){
			return other instanceof Pattern
				&& dashPhase == ((Pattern)other).dashPhase
				&& areEquals(dash, ((Pattern)other).dash);
		}
		
		private boolean areEquals(float[] array1,float[] array2){
			return toString(array1).equals(toString(array2));
		}
		private String toString(float[] array){
			StringBuilder builder = new StringBuilder();
			if (array != null){
				for (int i=0;i<array.length;i++){
					builder.append(array[i]).append(" ");
				}
			}
			return builder.toString();
		}
	}
	@Override
	protected boolean acceptObject(DrawingObject anObject) {
		return anObject instanceof ShapeObject;
	}
}
